﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Routing;
using Isha.Data;
using Isha.Entities;
using Isha.Services;
using System.Web.Mvc;
using Isha.Infrastructure;
using Microsoft.Practices.Unity;
using System.Threading;
using System.IO;
using Isha.Extensions;

namespace Isha.Web.Mvc
{
    public class IshaRoute : Route
    {
        private IUnityContainer Container { get; set; }
        // for admin
        const string portal_factory = "portal_factory";
        // for folder_contents
        string listcontents = Commands.ListContents.ToString().ToLower();

        public IshaRoute()
            : base(
                    null,
                    new RouteValueDictionary(new { controller = "IshaPage", action = "Index" }),
                    new MvcRouteHandler()
                  )
        {
            Container = IshaContext.Current.Container;
        }

        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            List<ContentItem> Breadcrum = new List<ContentItem>();
            IEnumerable<ContentItem> list = null;
            RouteData data = null;
            ContentItem contentItem = null;
            int? initialfolder = null;
            Commands DefaultCommand = Commands.Detail;
            string contenttype = "";
            int parentContentItemID = 1;

            IshaRequestContext RequestContext = IshaContext.Current.Request;
            ResourceDispatcherFactory.ProcessRequest(httpContext);

            // requested URL
            string requestUrl = RequestContext.URL;
            // Paths
            string[] linkPath = RequestContext.URL.Split('/');

            IContentTypeService ContentTypeService = IshaContext.Current.ServiceContext.ContentTypeService;
            IContentItemService ContentItemService = IshaContext.Current.ServiceContext.ContentItemService;

            for (int i = 0; i < linkPath.Length; i++)
            {
                string currentPath = IshaContext.Current.UrlFix(linkPath[i]);

                if (httpContext.Request.IsAuthenticated)
                {
                    if (currentPath.Equals(listcontents, StringComparison.OrdinalIgnoreCase))
                    {
                        RequestContext.IsFactoryAllowed = true;
                        RequestContext.IsAllowed = true;

                        list = ContentItemService.FetchContentItemsByParent(parentContentItemID);

                        initialfolder = 1;
                        DefaultCommand = Commands.ListContents;

                        if (parentContentItemID == 1)
                        {
                            contentItem = ContentItemService.FetchHome();
                            Breadcrum.Add(contentItem);
                            RequestContext.IsAllowed = true;
                        }

                        break;
                    }

                    if (currentPath.Equals(portal_factory, StringComparison.OrdinalIgnoreCase))
                    {
                        RequestContext.IsAllowed = true;
                        RequestContext.IsFactoryAllowed = true;

                        string contenttypes = ContentTypeService.ToString();

                        Match matchCreate = Regex.Match(requestUrl, "(" + portal_factory + ")/(" + contenttypes + ")/" + Commands.Create.ToString().ToLower() + "\\b", RegexOptions.IgnoreCase);
                        Match matchEdit = Regex.Match(requestUrl, "(" + portal_factory + ")/" + Commands.Edit.ToString().ToLower() + "\\b", RegexOptions.IgnoreCase);

                        if (matchCreate.Success)
                        {
                            contenttype = linkPath[linkPath.Length - 2];
                            DefaultCommand = Commands.Create;
                            contentItem = ContentItemService.FetchContentItem(parentContentItemID);
                            ///Breadcrum.Add(contentItem);

                            contentItem = new ContentItem();
                            IContentCommand contentCommand = Container.Resolve<IContentCommand>(contenttype);
                            contentItem.Type = (Type)contentCommand.GetType().GetCustomAttributesData()[0].ConstructorArguments[0].Value;
                            contentItem.Content = IshaContext.Current.Deserializer(contentItem.Type, contentItem.ContentXml);
                            
                            initialfolder = 1;

                            break;
                        }

                        if (matchEdit.Success)
                        {
                            contenttype = contentItem.ContentType.Title;
                            DefaultCommand = Commands.Edit;
                            initialfolder = 1;

                            break;
                        }
                    }
                }

                if (!string.IsNullOrEmpty(currentPath))
                {
                    if (contentItem == null)
                    {
                        //To select the first folder or item from contentitem table
                        contentItem = ContentItemService.FetchContentItemByLink(currentPath);
                        initialfolder = (contentItem == null) ? null : contentItem.ParentItemID;
                        RequestContext.IsAllowed = true;
                    }
                    else
                    {
                        //To select the item from contentitem table
                        contentItem = ContentItemService.FetchContentItemByLink(currentPath, contentItem.ContentItemID);
                    }

                    // To Validate Is URL is Validate Or AS Per Folder Structure   
                    if (RequestContext.IsAllowed && contentItem == null)
                    {
                        RequestContext.IsAllowed = false;
                        break;
                    }
                    else
                    {
                        parentContentItemID = contentItem.ContentItemID;
                    }

                    if (contentItem != null)
                        Breadcrum.Add(contentItem);
                }
                else if (contentItem == null && parentContentItemID == 1)
                {
                    //For Front Page                                             
                    contentItem = ContentItemService.FetchHome();
                    Breadcrum.Add(contentItem);

                    parentContentItemID = contentItem.ParentItemID.Value;
                    while (parentContentItemID > 1)
                    {
                        ContentItem parentContentItem = ContentItemService.FetchContentItem(parentContentItemID);
                        Breadcrum.Add(parentContentItem);
                        parentContentItemID = parentContentItem.ParentItemID.Value;
                    }

                    RequestContext.IsAllowed = true;
                    break;
                }
            }

            if (contentItem == null)
            {
                httpContext.Response.StatusCode = 404;
                contentItem = ContentItemService.Fetch404();
                initialfolder = 1;
                RequestContext.IsAllowed = true;
            }

            if (contentItem != null && (initialfolder == 1 || contentItem.ContentItemID == IshaContext.Current.Configuration.Home) && RequestContext.IsAllowed == true)
            {
                if (string.IsNullOrEmpty(contenttype))
                    contenttype = contentItem.ContentType.Title;
                
                this.Container.RegisterInstance<ContentItem>(contentItem, new HttpContextLifetimeManager<ContentItem>());

                IContentCommand contentCommand = Container.Resolve<IContentCommand>(contenttype.ToLower());
                contentItem.Type = (Type)contentCommand.GetType().GetCustomAttributesData()[0].ConstructorArguments[0].Value;

                if (contentItem.Content == null)
                    contentItem.Content = IshaContext.Current.Deserializer(contentItem.Type, contentItem.ContentXml);

                this.Container.RegisterInstance<IContentCommand>(contentCommand, new HttpContextLifetimeManager<IContentCommand>());
                this.Container.RegisterInstance<Commands>("IshaAction", DefaultCommand, new HttpContextLifetimeManager<Commands>());
                this.Container.RegisterInstance<List<ContentItem>>("Breadcrumbs", Breadcrum);

                if (list != null)
                    this.Container.RegisterInstance<IEnumerable<ContentItem>>("List", list);
            }

            if (RequestContext.IsAllowed)
            {
                data = new RouteData(this, this.RouteHandler);
                // add defaults first
                if (null != this.Defaults)
                {
                    if (RequestContext.IsFactoryAllowed == true)
                        data.Values["action"] = DefaultCommand.ToString();

                    foreach (KeyValuePair<string, object> def in this.Defaults)
                    {
                        if (data.Values[def.Key] == null)
                            data.Values[def.Key] = def.Value;
                    }

                }
            }

            return data;
        }
    }

}